<template>
  <t-upload
    :action="postObjectParams.host"
    placeholder="支持批量上传文件，文件格式不限，最多只能上传 10 份文件"
    theme="file-flow"
    multiple
    :disabled="disabled"
    :abridge-name="[10, 7]"
    :auto-upload="autoUpload"
    :max="10"
    :show-thumbnail="showThumbnail"
    :allow-upload-duplicate-file="allowUploadDuplicateFile"
    :is-batch-upload="isBatchUpload"
    :upload-all-files-in-one-request="uploadAllFilesInOneRequest"
    :format-response="formatResponse"
    :format-request="formatRequest"
    :before-all-files-upload="beforeAllFilesUpload"
    :headers="headers"
  />
</template>

<script setup lang="ts">
import CryptoJS from 'crypto-js';
import { FormatResponseContext, MessagePlugin, UploadFile } from 'tdesign-vue-next';
import { ref } from 'vue';

import { useUserStore } from '@/store';
import { request } from '@/utils/request';

// 用户仓库
const userStore = useUserStore();
// post对象参数
const postObjectParams = ref<Record<string, any>>({});
// 文件名称映射
const fileNameMap = ref<Record<string, string>>({});
const disabled = ref(false);
const autoUpload = ref(false);
const showThumbnail = ref(true);
const allowUploadDuplicateFile = ref(false);
const isBatchUpload = ref(false);
const uploadAllFilesInOneRequest = ref(false);
// 全部文件上传之前
const beforeAllFilesUpload = async (file: UploadFile[]) => {
  try {
    // 生成文件名称映射
    file.forEach(async (item) => {
      fileNameMap.value[item.name] = await generateFileName(item.raw);
    });
    // 获取post对象参数
    const result = await request.get({
      url: '/infra/file/post-object-params',
    });
    postObjectParams.value = result;
    return true;
  } catch {
    MessagePlugin.error('获取上传文件参数失败');
    return false;
  }
};
// 请求头
const headers = ref({
  Authorization: `Bearer ${userStore.token}`,
});
// 生成文件名称
const generateFileName = async (file: File) => {
  // 读取文件内容
  const data = await file.arrayBuffer();
  const wordArray = CryptoJS.lib.WordArray.create(data);
  // 计算SHA256
  const sha256 = CryptoJS.SHA256(wordArray).toString();
  // 拼接后缀
  const ext = file.name.substring(file.name.lastIndexOf('.'));
  return `${sha256}${ext}`;
};
// 格式化请求体
const formatRequest = (requestData: Record<string, any>) => {
  return {
    success_action_status: '200',
    policy: postObjectParams.value.policy,
    'x-oss-signature': postObjectParams.value.signature,
    'x-oss-signature-version': postObjectParams.value.version,
    'x-oss-credential': postObjectParams.value.credential,
    'x-oss-date': postObjectParams.value.ossdate,
    key: `${postObjectParams.value.dir}${fileNameMap.value[requestData.file.name]}`,
    'x-oss-security-token': postObjectParams.value.token,
    file: requestData.file,
  };
};
// 格式化响应体
const formatResponse = (response: Record<string, any>, context: FormatResponseContext) => {
  return {
    url: `${postObjectParams.value.host}/${postObjectParams.value.dir}${fileNameMap.value[context.file.name]}`,
  };
};
</script>
